<?php
/**
 * MageWorx
 *
 * NOTICE OF LICENSE
 *
 * This source file is subject to the MageWorx EULA that is bundled with
 * this package in the file LICENSE.txt.
 * It is also available through the world-wide-web at this URL:
 * http://www.mageworx.com/LICENSE-1.0.html
 *
 * If you did not receive a copy of the license and are unable to
 * obtain it through the world-wide-web, please send an email
 * to license@mageworx.com so we can send you a copy immediately.
 *
 * DISCLAIMER
 *
 * Do not edit or add to this file if you wish to upgrade the extension
 * to newer versions in the future. If you wish to customize the extension
 * for your needs please refer to http://www.mageworx.com/ for more information
 * or send an email to sales@mageworx.com
 *
 * @category   MageWorx
 * @package    MageWorx_DeliveryZone
 * @copyright  Copyright (c) 2009 MageWorx (http://www.mageworx.com/)
 * @license    http://www.mageworx.com/LICENSE-1.0.html
 */

/**
 * Delivery Zone extension
 *
 * @category   MageWorx
 * @package    MageWorx_DeliveryZone
 * @author     MageWorx Dev Team <dev@mageworx.com>
 */

class MageWorx_DeliveryZone_Model_Mysql4_Zone extends Mage_Core_Model_Mysql4_Abstract
{
    protected $_type  = null;
    protected $_table = array(
        'C' => 'category',
        'S' => 'shippingmethod',
    );

    public function _construct()
    {
        $this->_init('deliveryzone/zone', 'zone_id');
    }

    protected function _afterLoad(Mage_Core_Model_Abstract $object)
    {
        $select = $this->_getReadAdapter()->select()
            ->from($this->getTable('deliveryzone/'.$this->_table[$object->getType()]))
            ->where('zone_id = ?', $object->getId());

        switch($object->getType()) {
            case MageWorx_DeliveryZone_Model_Zone::ZONE_TYPE_CATEGORY:
                $categoryIds = array();
                if ($data = $this->_getReadAdapter()->fetchAll($select)) {
                    foreach ($data as $row) {
                        $categoryIds[] = $row['category_id'];
                    }
                }
                $object->setData('category_ids', $categoryIds);

                $cats = Mage::getResourceModel('catalog/category_collection')
                    ->addIdFilter($categoryIds)
                    ->addNameToResult()
                    ->load()
                    ->getColumnValues('name');
                $object->setData('categories_brief', implode(', ', array_slice($cats, 0, 5)) . (count($cats) > 5 ? ', ... ('.count($cats).')' : '' ));
                break;

            case MageWorx_DeliveryZone_Model_Zone::ZONE_TYPE_SHIPPINGMETHOD:
                if ($data = $this->_getReadAdapter()->fetchAll($select)) {
                    $shipping = Mage::getSingleton('shipping/config');
                    $configFields = Mage::getSingleton('adminhtml/config');
                    $section  = 'carriers';
                    $sections = $configFields->getSections($section);
                    $section  = $sections->$section->groups;
                    $active   = $methods = $carriers = array();
                    foreach ($data as $row) {
                        $active[$row['carrier_id'].'_active'] = 1;
                        $methods[$row['carrier_id'].'_methods'] = explode(',', $row['allowed_methods']);
                        $carriers[$row['carrier_id']] = (string) $section->{$row['carrier_id']}->label;
                    }
                    ksort($carriers);
                    $object->setData('shippingmethods_brief', implode(', ', array_slice($carriers, 0, 7)) . (count($carriers) > 7 ? ', ... ('.count($carriers).')' : '' ));
                    $object->setData($object->getData() + $active + $methods);
                }
                break;
        }
        $select = $this->_getReadAdapter()->select()
            ->from($this->getTable('deliveryzone/location'), array('country_id', 'region_ids'))
            ->where('location_id = ?', $object->getLocationId());

        if ($locations = $this->_getReadAdapter()->fetchPairs($select)) {
            ksort($locations);
            foreach ($locations as $countryId => $regionIds){
                $countries[$countryId] = $countryId . (!empty($regionIds) ? ' (' . count(array_filter(explode(',', $regionIds))) . ')' : '');
            }
            $object->setData('countries_brief', implode(', ', array_slice($countries, 0, 10)) . (count($countries) > 10 ? ', ... ('.count($countries).')' : '' ));
        }
        return parent::_afterLoad($object);
    }

    protected function _afterSave(Mage_Core_Model_Abstract $object)
    {
        switch ($this->_type) {
            case MageWorx_DeliveryZone_Model_Zone::ZONE_TYPE_CATEGORY:
                $categoryIds = array_filter(array_unique(explode(',', (string) $object->getData('category_ids'))));
                if (!empty($categoryIds)){
                    $condition = $this->_getWriteAdapter()->quoteInto('zone_id = ?', $object->getId());
                    $this->_getWriteAdapter()->delete($this->getTable('deliveryzone/category'), $condition);

                    foreach ($categoryIds as $categoryId) {
                        $category = array();
                        $category['zone_id']     = $object->getId();
                        $category['category_id'] = $categoryId;
                        $this->_getWriteAdapter()->insert($this->getTable('deliveryzone/category'), $category);
                    }
                }
                break;

            case MageWorx_DeliveryZone_Model_Zone::ZONE_TYPE_SHIPPINGMETHOD:
                $activeCarriers = (array) $object->getData('active');
                $allowedMethods = (array) $object->getData('methods');
                if (!empty($activeCarriers)){
                    $condition = $this->_getWriteAdapter()->quoteInto('zone_id = ?', $object->getId());
                    $this->_getWriteAdapter()->delete($this->getTable('deliveryzone/shippingmethod'), $condition);

                    foreach ($activeCarriers as $carrierId => $isActive) {
                        if ($isActive){
                            $carrier = array();
                            $carrier['zone_id']    = $object->getId();
                            $carrier['carrier_id'] = $carrierId;
                            if (isset($allowedMethods[$carrierId])){
                                $carrier['allowed_methods'] = implode(',', $allowedMethods[$carrierId]);
                            }
                            $this->_getWriteAdapter()->insert($this->getTable('deliveryzone/shippingmethod'), $carrier);
                        }
                    }
                }
                break;
		}

        if ($countries = (array) $object->getData('countries')) {
            $regions = (array) $object->getData('regions');
            if ($locationId = $object->getLocationId()) {
                $condition = $this->_getWriteAdapter()->quoteInto('location_id = ?', $object->getLocationId());
                $this->_getWriteAdapter()->delete($this->getTable('deliveryzone/location'), $condition);
            } else {
                $select = $this->_getReadAdapter()->select();
                $select->from($this->getTable('deliveryzone/location'), new Zend_Db_Expr('IFNULL(MAX(location_id), 0) + 1'));
                $locationId = $this->_getReadAdapter()->fetchOne($select);
            }
            foreach ($countries as $countryId) {
                $location = array();
                $location['location_id'] = $locationId;
                $location['country_id']  = $countryId;
                if (isset($regions[$countryId]) && !empty($regions[$countryId])) {
                    $location['region_ids'] = ',' . implode(',', $regions[$countryId]) . ',';
                }
                $this->_getWriteAdapter()->insert($this->getTable('deliveryzone/location'), $location);
            }
            $condition = $this->_getWriteAdapter()->quoteInto('zone_id = ?', $object->getId());
            $this->_getWriteAdapter()->update($this->getMainTable(), array('location_id' => $locationId), $condition);
        }

        return parent::_afterSave($object);
    }

    public function getByLocation(Varien_Object $location)
    {
        $select = $this->_getReadAdapter()->select()
            ->from(array('d' => $this->getTable('deliveryzone/'.$this->_table[$this->_type])), $this->_type == MageWorx_DeliveryZone_Model_Zone::ZONE_TYPE_CATEGORY ? 'category_id' : array('carrier_id', 'allowed_methods'))
            ->join(array('z' => $this->getMainTable()), 'd.zone_id = z.zone_id', null)
            ->join(array('l' => $this->getTable('deliveryzone/location')), 'z.location_id = l.location_id', null)
            ->where('country_id = ?', $location->getCountryId());

		if ($regionId = $location->getRegionId()) {
            $select->where('region_ids LIKE ?', '%,'.$regionId.',%');
        }
        switch ($this->_type) {
            case MageWorx_DeliveryZone_Model_Zone::ZONE_TYPE_CATEGORY:
                return $this->_getReadAdapter()->fetchCol($select);

            case MageWorx_DeliveryZone_Model_Zone::ZONE_TYPE_SHIPPINGMETHOD:
                return $this->_getReadAdapter()->fetchPairs($select);
        }
    }

    public function getZoneIdsByLocation(Varien_Object $location)
    {
        $select = $this->_getReadAdapter()->select()
            ->from(array('z' => $this->getMainTable()), 'zone_id')
            ->join(array('l' => $this->getTable('deliveryzone/location')), 'z.location_id = l.location_id', null)
            ->where('country_id = ?', $location->getCountryId());

        if ($regionId = $location->getRegionId()) {
            $select->where('region_ids LIKE ?', '%,'.$regionId.',%');
        }
        return $this->_getReadAdapter()->fetchCol($select);
    }

    public function getProductIdsByLocation(Varien_Object $location)
    {
        $categoryIds = $this->getByLocation($location);
        $productTable = $this->getTable('catalog/category_product');
        $select = $this->_getReadAdapter()->select();
        $select->from($productTable, 'product_id')
            ->where('category_id IN (?)', $categoryIds);
        return $this->_getReadAdapter()->fetchCol($select);
    }

    protected function _getLoadSelect($field, $value, $object)
    {
        $select = parent::_getLoadSelect($field, $value, $object);
        if ($this->_type) {
            $select->where('type = ?', $this->_type);
        }
        return $select;
    }

    public function setType($type)
    {
        $this->_type = $type;
        return $this;
    }
}